//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace Microsoft.Research.DataLayer
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    /// <summary>
    /// 
    /// </summary>
    [Serializable]
    public class ActivityBeforeCalls : IDataLayerSecurityBeforeCalls
    {
        private Connection connection;

        /// <summary>
        /// Initializes a new instance of the <see cref="ActivityBeforeCall"/> class.
        /// </summary>
        /// <param name="connection">The connection.</param>
        public ActivityBeforeCalls(Connection connection)
        {
            this.connection = connection;
        }

        #region IDataLayerSecurityBeforeCalls Members
        /// <summary>
        /// Objects the specified error.
        /// </summary>
        /// <param name="error">The error.</param>
        /// <param name="storage">The storage.</param>
        /// <param name="action">The action.</param>
        /// <param name="paramList">The param list.</param>
        /// <returns></returns>
        public SecurityAction Object(out Exception error, ref Connection.Storage storage,
            ref Connection.Action action, ref List<Parameter> paramList)
        {
            error = null;

            if (storage.Name.Equals("Activity", StringComparison.OrdinalIgnoreCase))
            {
                switch (action)
                {
                    case Connection.Action.Delete:
                    case Connection.Action.Update:
                        {
                            Parameter idParam = paramList
                                .FirstOrDefault(param => param.Name.Equals("ID", StringComparison.OrdinalIgnoreCase));

                            if (idParam != null)
                            {
                                Activity activity = Activity.Load((Guid)idParam.Value, connection);
                                if (activity.IsWorkflow)
                                {
                                    return CheckAuthor(ref error, ActivitySecurity.GetUser(this.connection), activity);
                                }
                            }
                            break;
                        }
                }
            }

            return SecurityAction.Allow;
        }

        /// <summary>
        /// Objects the specified error.
        /// </summary>
        /// <param name="error">The error.</param>
        /// <param name="storage">The storage.</param>
        /// <param name="action">The action.</param>
        /// <param name="creator">The creator.</param>
        /// <param name="results">The results.</param>
        /// <returns></returns>
        public SecurityAction Object(out Exception error, ref Connection.Storage storage,
            ref Connection.Action action, Connection.ObjectCreator creator, ref List<IObject> results)
        {
            error = null;
            // No Filters will be applied when LoadAll.

            return SecurityAction.Allow;
        }

        public SecurityAction Relation(out Exception error, ref Connection.Action action, ref IObject obj1, ref IObject obj2)
        {
            error = null;
            // No Filters will be applied when LoadAll.

            return SecurityAction.Allow;
        }

        public SecurityAction Relation(out Exception error, ref Connection.Action action, ref IObject obj1, ref Connection.Storage obj2, ref string revKey, ref List<Parameter> paramList)
        {
            error = null;
            // No Filters will be applied when LoadAll.

            return SecurityAction.Allow;
        }

        public SecurityAction Relation(out Exception error, ref Connection.Action action, ref IObject obj1, ref Connection.Storage obj2Type, Connection.ObjectCreator creator, ref List<IObject> results)
        {
            error = null;
            // No Filters will be applied when LoadAll.

            return SecurityAction.Allow;
        }

        public SecurityAction Relation(out Exception error, ref Connection.Action action, ref IObject obj1, ref string field, ref Connection.Storage obj2Type, Connection.ObjectCreator creator, ref List<IObject> results)
        {
            error = null;
            // No Filters will be applied when LoadAll.

            return SecurityAction.Allow;
        }
        #endregion

        #region Private methods
        /// <summary>
        /// Checks for author permission.
        /// </summary>
        /// <param name="error">The error.</param>
        /// <param name="currentUser">The current user.</param>
        /// <param name="activity">The activity.</param>
        /// <returns></returns>
        private static SecurityAction CheckAuthor(ref Exception error, User currentUser, Activity activity)
        {
            if (!activity.Security.Rights.AuthorWorkflow.Check(currentUser))
            {
                error = new System.Security.SecurityException("Does not author permission.");
                return SecurityAction.Deny;
            }
            else
            {
                return SecurityAction.Allow;
            }
        }
        #endregion
    }
}
